package com.dragon.logical.service.avttendance.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dragon.common.model.ResultCode;
import com.dragon.common.model.exception.CustomException;
import com.dragon.logical.service.avttendance.IAttendanceLeaveService;
import com.dragon.repository.config.annotation.DataScope;
import com.dragon.repository.entity.*;
import com.dragon.repository.mapper.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;

/**
 * <p>
 * 请假表 服务实现类
 * </p>
 *
 * @author sy
 * @since 2023-07-20
 */
@Service
public class AttendanceLeaveServiceImpl extends ServiceImpl<AttendanceLeaveMapper, AttendanceLeave> implements IAttendanceLeaveService {

    @Autowired
    AttendanceLeaveMapper leaveMapper;
    @Autowired
    AttendanceMapper attendanceMapper;
    @Autowired
    AdminMapper adminMapper;
    @Autowired
    OtherFileMapper fileMapper;
    @Autowired
    ArrangePersonnelMapper arrangePersonnelMapper;

    @Override
    @DataScope(adminAlias = "M", adminField = "admin_id,to_id", deptAlias = "M", deptField = "department_id")
    public Page<AttendanceLeave> leaveList(Integer page, Integer limit ,Integer adminId) {
        Page<AttendanceLeave> leavePage = new Page<>(page, limit);
        QueryWrapper<AttendanceLeave> wrapper = new QueryWrapper<>();
        wrapper.eq(adminId != null, "M.admin_id", adminId)
                .orderByDesc("M.create_time");
        return leaveMapper.selectLeavePage(leavePage,wrapper);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public AddPageData addLeave(AttendanceLeave leave) {
        //同一天不能请两次假
        List<AttendanceLeave> leaveList = leaveMapper.selectList(new QueryWrapper<AttendanceLeave>()
                .lambda()
                .eq(AttendanceLeave::getAdminId, leave.getAdminId())
                .eq(AttendanceLeave::getStatus, 0));
        AtomicReference<Boolean> flag = new AtomicReference<>(false);
        AtomicReference<Boolean> flag2 = new AtomicReference<>(false);
        leaveList.forEach(leave1 -> {
            flag.set(belongCalendar(leave.getStartTime(), leave1.getStartTime(), leave1.getEndTime()));
            flag.set(belongCalendar(leave.getEndTime(), leave1.getStartTime(), leave1.getEndTime()));
            if (flag.get() == true || flag2.get() == true ){
                throw new CustomException(ResultCode.ATTENDANCE_LEAVE_REPEAT_CREATE);
            }
        });
        leave.setCreateTime(DateUtil.date());
        leaveMapper.insert(leave);
        if (leave.getOtherFiles() != null && leave.getOtherFiles().size()!=0){
            for (OtherFile otherFile : leave.getOtherFiles()) {
                otherFile.setStreamType(13);
                otherFile.setCorrelationId(leave.getId());
                otherFile.setCreateTime(DateUtil.date());
                fileMapper.insert(otherFile);
            }
        }

        Admin admin = adminMapper.selectById(leave.getAdminId());
        AddPageData addPageData = new AddPageData();
        addPageData.setAdminId(leave.getAdminId());
        addPageData.setWorkflowJson(leave.getWorkflowJsonList());
        addPageData.setStreamType(13);
        addPageData.setCorrelationId(leave.getId());
        addPageData.setExempt(leave.getExempt());
        addPageData.setTitle("【"+admin.getUsername()+"】的请假");
        return addPageData;
    }

    @Override
    public AttendanceLeave detailLeave(Integer id) {
        AttendanceLeave leave = leaveMapper.selectDetail(id);
        List<OtherFile> otherFileList = fileMapper.selectList(new QueryWrapper<OtherFile>()
                .lambda().eq(OtherFile::getStreamType, 13)
                .eq(OtherFile::getCorrelationId, id));
        leave.setOtherFiles(otherFileList);
        return leave;
    }

    @Override
    public void auditLeave(Integer status, Integer mainId){

        AttendanceLeave leave = leaveMapper.selectById(mainId);
        leave.setStatus(status);
        //获取用户的考勤配置
        ArrangePersonnel arrangePersonnel = arrangePersonnelMapper.selectOne(new QueryWrapper<ArrangePersonnel>()
                .lambda()
                .eq(ArrangePersonnel::getAdminId, leave.getAdminId()));
        if (status == 1){
            //计算 请假了多少天
            long betweenDay = DateUtil.between(leave.getStartTime(), leave.getEndTime(), DateUnit.DAY);
            if (betweenDay == 0){
                betweenDay = 1;
            }
            for (int i = 0; i < betweenDay; i++) {
                //查看 当天 是否有打卡信息
                DateTime leaveTime = DateUtil.offsetDay(leave.getStartTime(), i);
                QueryWrapper<Attendance> wrapper = new QueryWrapper<>();
                Attendance attendance = attendanceMapper.selectOne(wrapper.lambda()
                        .eq(Attendance::getAdminId, leave.getAdminId())
                        .apply(" date_format(create_time,'%y%mm%dd%') = date_format('" + leaveTime + "','%y%mm%dd%')"));
                if (attendance == null){
                    Attendance attendance1 = new Attendance();
                    attendance1.setAttendanceType(2);
                    attendance1.setCreateTime(leaveTime);
                    attendance1.setAdminId(leave.getAdminId());
                    attendance1.setDepartmentId(leave.getDepartmentId());
                    attendance1.setLeaveDuration(leave.getDuration());
                    attendance1.setArrangeId(arrangePersonnel.getArrangeId());
                    attendanceMapper.insert(attendance1);
                    leave.setAttendanceId(attendance1.getId());
                } else {
                    attendance.setAttendanceType(2);
                    attendance.setLeaveDuration(leave.getDuration());
                    attendanceMapper.updateById(attendance);
                    leave.setAttendanceId(attendance.getId());
                }
                leaveMapper.updateById(leave);
            }
        }
    }


    /**
     * 判断时间是否处于某个时间段内
     *
     * @param time 需要比较的时间
     * @param from 起始时间
     * @param to 结束时间
     * @return
     */
    public static boolean belongCalendar(Date time, Date from, Date to) {
        Calendar date = Calendar.getInstance();
        date.setTime(time);
        Calendar after = Calendar.getInstance();
        after.setTime(from);
        Calendar before = Calendar.getInstance();
        before.setTime(to);
        if (date.after(after) && date.before(before)) {
            return true;
        } else {
            return false;
        }
    }
}
